// Contient toutes les spécifications de classes nécessaires
// pour représenter l'arbre abstrait
#ifndef ARBRE_H_
#define ARBRE_H_

#include <vector>
#include <iostream>
#include <iomanip>
using namespace std;

#include "Symbole.h"

/*! \file Arbre.h
    \brief La spécification des classes Noeud
    
    Décrit la liste des méthodes et attributs associés aux classes Noeud
    \author lazzamar
    \date 16/12/2012
 */
/*! \class Noeud
    \brief La classe mère représentant les noeud de l'arbre.
    
    Cette classe permet de construire les noeud de l'arbre abstrait.
 Les méthodes suivantes sont utiliés pour évaluer le programme et l'afficher
 * \li getValeur
 * \li afficher
 * 
 * D'autres fonctions liès aux instructions existe pour les construire avec précision.
*/

////////////////////////////////////////////////////////////////////////////////
class Noeud {
// classe abstraite dont dériveront toutes les classes servant à représenter l'arbre abstrait
// Remarque : la classe ne contient aucun constructeur
  public:
	/*! \fn int  getValeur();
	 *	\brief Evalue l'arbre.
	 * 
	 * Cette fonction évalue le programme et retourne une valeur à chaque appel
	 * (qui dépend du noeud).
	 * 
	 * \return Une valeur entière qui dépend des noeuds évalués.
	 */
    virtual int  getValeur() =0 ; // méthode pure (non implémentée) qui rend la classe abstraite
	
	/*! \fn void afficher(unsigned short indentation=0);
	 *	\brief Affiche l'arbre.
	 * 
	 * Cette fonction affiche le programme lu sous forme d'arbre, suivant une
	 * indentation.
	 * 
	 * \param unsigned short indentation - La valeur de l'indentation dans l'arbre.
	 */
    virtual void afficher(unsigned short indentation=0) { cout << setw(4*indentation) << " "; }
      // pour afficher un noeud avec un décalage (indentation) proportionnel à son niveau dans l'arbre

    virtual ~Noeud() {} // présence d'un destructeur virtuel conseillée dans les classes abstraites
};

////////////////////////////////////////////////////////////////////////////////
class NoeudSeqInst : public Noeud {
// classe pour représenter un noeud "sequence d'instruction"
// qui a autant de fils que d'instructions dans la séquence
  public:
     NoeudSeqInst();   // construit une séquence d'instruction vide
    ~NoeudSeqInst() {} // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue chaque instruction de la séquence
    void afficher(unsigned short indentation=0); // affiche la séquence d'instructions
    void ajouteInstruction(Noeud* instruction);  // ajoute une instruction à la séquence

  private:
    vector<Noeud *> tabInst; // pour stocker les instructions de la séquence
};

////////////////////////////////////////////////////////////////////////////////
class NoeudAffectation : public Noeud {
// classe pour représenter un noeud "affectation"
// composé de 2 fils : la variable et l'expression qu'on lui affecte
  public:
     NoeudAffectation(Noeud* variable, Noeud* expression); // construit une affectation
    ~NoeudAffectation() {} // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue l'expression et affecte sa valeur à la variable
    void afficher(unsigned short indentation=0); // affiche l'affectation

  private:
    Noeud* variable;
    Noeud* expression;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudOperateurUnaire : public Noeud {
// classe pour représenter un noeud "opération unaire" composé d'un opérateur
// unaire (- non) et d'un fils : l'opérande
public:
	NoeudOperateurUnaire(Symbole operateur, Noeud* operande);
	~NoeudOperateurUnaire() {} // à cause du destructeur virtuel de la classe Noeud
	int getValeur(); // évalue l'opérande gauche et applique l'opérateur
	void afficher(unsigned short indentation=0); //affiche l'opération;
private:
	Symbole	operateur;
	Noeud*	operande;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudOperateurBinaire : public Noeud {
// classe pour représenter un noeud "opération arithmétique" composé d'un opérateur (+-*/)
// et de 2 fils : l'opérande gauche et l'opérande droit
  public:
    NoeudOperateurBinaire(Symbole operateur, Noeud* operandeGauche, Noeud* operandeDroit);
     // construit une opération binaire : operandeGauche operateur OperandeDroit
   ~NoeudOperateurBinaire() {} // à cause du destructeur virtuel de la classe Noeud
    int getValeur(); // évalue l'operande gauche, l'operande droit et applique l'opérateur
    void afficher(unsigned short indentation=0); // affiche l'opération

  private:
    Symbole operateur;
    Noeud*  operandeGauche;
    Noeud*  operandeDroit;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudInstSi : public Noeud {
// classe pour représenter un noeud d'une instruction conditionnelle "si"
// composée de deux vector : un de conditions lié à un vector de sequence
// d'instruction
public:
	NoeudInstSi(); // construit des conditions/sequences vides
	~NoeudInstSi(){} // à cause du destructeur virtuel de la classe Noeud
	int getValeur(); // évalue la bonne sequence d'instruction
	void afficher(unsigned short indentation = 0); // affiche l'instruction
	void ajoute(Noeud* condition, Noeud* sequence);  // ajoute une condition et
									// une sequence d'instruction à l'instruction

private:
	vector<Noeud *> tabCond;// pour stocker les conditions
	vector<Noeud *> tabSeq;	// pour stocker les sequences d'instruction
};

////////////////////////////////////////////////////////////////////////////////
class NoeudInstSelon : public Noeud {
// classe pour représenter un noeud d'une instruction conditionnelle "selon"
// composée d'une variable qui sera comparée et de deux vector :
// un de conditions lié à un vector de sequence d'instruction
public:
	NoeudInstSelon(Noeud* variable); // initialise la variable et
									// construit des conditions/sequences vides
	~NoeudInstSelon(){} // à cause du destructeur virtuel de la classe Noeud
	int getValeur(); // évalue la bonne sequence d'instruction
	void afficher(unsigned short indentation = 0); // affiche l'instruction
	void ajoute(Noeud* condition, Noeud* sequence);  // ajoute une condition et
									// une sequence d'instruction à l'instruction

private:
	Noeud* variable;
	vector<Noeud *> tabCond;// pour stocker les conditions
	vector<Noeud *> tabSeq;	// pour stocker les sequences d'instruction
};

////////////////////////////////////////////////////////////////////////////////
class NoeudIter : public Noeud {
// classe mère des itérations possédant deux membres :
// une condition et une séquence d'instruction
public:
	~NoeudIter(){}
	int getValeur();
	void afficher();
	
	//getters et setters pour les attributs
	inline void setCond(Noeud* cond){this->cond=cond;}
	inline void setSeqInst(Noeud* seqInst){this->seqInst=seqInst;}
	inline Noeud* getCond(){return this->cond;}
	inline Noeud* getSeqInst(){return this->seqInst;}
private:
	Noeud* cond; // la condition de la boucle
	Noeud* seqInst; // la séquence à exécuter
};

////////////////////////////////////////////////////////////////////////////////
class NoeudInstTq : public NoeudIter {
// classe pour représenter un noeud d'une instruction itérative "tantque"
// hérite de NoeudIter
public:
	NoeudInstTq(Noeud* cond, Noeud* seqInst); // construit la condition/sequence
	~NoeudInstTq(){} // à cause du destructeur virtuel de la classe Noeud
	void afficher(unsigned short indentation = 0); // affiche l'instruction
};

////////////////////////////////////////////////////////////////////////////////
class NoeudInstRepeter : public NoeudIter {
// classe pour représenter un noeud d'une instruction itérative "repeter"
// hérite de NoeudIter
public:
	NoeudInstRepeter(Noeud* cond, Noeud* seqInst); // construit la condition/sequence
	~NoeudInstRepeter(){} // à cause du destructeur virtuel de la classe Noeud
	int getValeur(); // rajoute l'évaluation de séquence obligatoire du Repeter
	void afficher(unsigned short indentation = 0); // affiche l'instruction
};

////////////////////////////////////////////////////////////////////////////////
class NoeudInstPour : public NoeudIter {
// classe pour représenter un noeud d'une instruction itérative "pour"
// hérite de NoeudIter
public:
	NoeudInstPour(Noeud* affect, Noeud* cond, Noeud* instr, Noeud* seqInst); // construit l'affectation/condition/sequence
	~NoeudInstPour() {} // à cause du destructeur virtuel de la classe Noeud
	int getValeur(); // rajoute l'évaluation de l'affectation du pour
	void afficher(unsigned short indentation = 0); // affiche l'instruction
	
private:
	Noeud* affect; //l'affectation utilisée pour le "pour"
};

////////////////////////////////////////////////////////////////////////////////
class NoeudInstLire : public Noeud {
public:
	NoeudInstLire(Noeud* variable);
	~NoeudInstLire() {} //à cause du destructeur virtuel de la classe Noeud
	int getValeur(); // évalue la lecture
	void afficher(unsigned short indentation = 0); //affiche l'instruction
	
private :
	Noeud* variable;
};

////////////////////////////////////////////////////////////////////////////////
class NoeudInstEcrire : public Noeud {
public:
	NoeudInstEcrire(Noeud* contenu);
	~NoeudInstEcrire() {} //à cause du destructeur virtuel de la classe Noeud
	int getValeur(); // évalue l'écriture
	void afficher(unsigned short indentation = 0); //affiche l'instruction
	
private :
	Noeud* contenu;
};

#endif /* ARBRE_H_ */
